/******************************************************************************
 * @file     intrrupt_test.c
 * @version  V0.10
 * $Revision: 1 $
 * $Date: 21/02/23 9:23a $
 * @brief    IEC60730 Interrupt Test
 * @note
 * SPDX-License-Identifier: Apache-2.0
 * Copyright (C) 2016-2020 Nuvoton Technology Corp. All rights reserved.
 ******************************************************************************/

#include <stdio.h>
#include "nuc980.h"
#include "IEC60730_CONTROL_PARAM.h"
#include "IEC60730_SAFETY_TEST_LIB.h"

volatile uint32_t u32SysTickCnt;
volatile uint32_t u32Timer0Cnt, u32Timer1Cnt;
uint32_t u32TimerRatio;
uint32_t u32TimeDevation;
//volatile uint32_t u32TimerIntFlag0;
static uint8_t volatile u8WDTINT = FALSE;
static uint8_t volatile u8TestResult = TEST_FAIL;

/*-------------------------------------------*/
/*                timer0 isr                 */
/*-------------------------------------------*/
void ETMR0_IRQHandler(void)
{
    /* clear timer0 interrupt flag */
    ETIMER_ClearIntFlag(TIMER0);

    /* increase timer count for startup test */
    u32Timer0Cnt++;
//    u32TimerIntFlag0 = 1;
}

/*-------------------------------------------*/
/*                timer1 isr                 */
/*-------------------------------------------*/
void ETMR1_IRQHandler(void)
{
    /* clear timer0 interrupt flag */
    ETIMER_ClearIntFlag(TIMER1);

    /* increase timer count for startup test */
    u32Timer1Cnt++;
}

/*-------------------------------------------*/
/*                init timer0                */
/*-------------------------------------------*/
static void InitTimer0(void)
{
    /* select timer0 clock from clk_in (12 MHz) */
    outpw(REG_CLK_DIVCTL8, inpw(REG_CLK_DIVCTL8) & ~0x30000);

    /* enable ETIMER0 engine clock */
    outpw(REG_CLK_PCLKEN0, inpw(REG_CLK_PCLKEN0) | (1 << 8));

    /* set timer0 frequency (Hz) */
    ETIMER_Open(TIMER0, ETIMER_PERIODIC_MODE, TIMER0_STARTUP_FREQ);

}


/*-------------------------------------------*/
/*                init timer1                */
/*-------------------------------------------*/
static void InitTimer1(void)
{

#ifdef TIMER1_STARTUP_FROM_32K
    /* enable 32K clock input */
    outpw(REG_CLK_PCLKEN0, inpw(REG_CLK_PCLKEN0) | BIT2);
    RTC->INIT = RTC_INIT_KEY;
    while(!((RTC->INIT) & 0x01));
    RTC_WaitAccessEnable();
    outpw(REG_RTC_CLKCTL, inpw(REG_RTC_CLKCTL) | BIT0);
    RTC_Check();

    /* select timer1 clock from 32k */
    outpw(REG_CLK_DIVCTL8, inpw(REG_CLK_DIVCTL8) | 0xC0000);
#else
    /* select timer1 clock from PCLK */
    outpw(REG_CLK_DIVCTL8, (inpw(REG_CLK_DIVCTL8) & ~0x000C0000) | 0x00040000);
#endif
    /* enable ETIMER1 engine clock */
    outpw(REG_CLK_PCLKEN0, inpw(REG_CLK_PCLKEN0) | (1 << 9));

    /* set timer1 frequency (Hz) */
    ETIMER_Open(TIMER1, ETIMER_PERIODIC_MODE, TIMER1_STARTUP_FREQ);
}

uint8_t IEC60730_Interrupt_Test(void)
{
    uint8_t u8IntTestPass;
    
    /* init timer0 */
    InitTimer0();
    u32Timer0Cnt = 0;

    /* setup timer0 interrupt */
    ETIMER_ClearIntFlag(TIMER0);
    sysInstallISR(IRQ_LEVEL_1, IRQ_TIMER0, (PVOID)ETMR0_IRQHandler);
    ETIMER_EnableInt(TIMER0);
    sysEnableInterrupt(IRQ_TIMER0);

    /* init timer1 */
    InitTimer1();
    u32Timer1Cnt = 0;

    /* setup timer1 interrupt */
    ETIMER_ClearIntFlag(TIMER1);
    sysInstallISR(IRQ_LEVEL_1, IRQ_TIMER1, (PVOID)ETMR1_IRQHandler);
    ETIMER_EnableInt(TIMER1);
    sysEnableInterrupt(IRQ_TIMER1);

    /* enable global interrupt */
    sysSetLocalInterrupt(ENABLE_IRQ);

    /* start timer0 and timer1 */
    ETIMER_Start(TIMER0);
    ETIMER_Start(TIMER1);

    while(u32Timer1Cnt<TIMER1_STARTUP_FREQ);

    /* check test result */
    if ((u32Timer0Cnt>= TIMER0_STARTUP_FREQ-TIMER_DEVATION)
            && (u32Timer0Cnt<= TIMER0_STARTUP_FREQ+TIMER_DEVATION))
        u8IntTestPass = TEST_PASS;
    else
        u8IntTestPass = TEST_FAIL;

    /* stop timer0 and timer1 */
    ETIMER_Stop(TIMER0);
    ETIMER_Stop(TIMER1);

    /* disable interrupt */
    sysSetLocalInterrupt(DISABLE_IRQ);
    ETIMER_DisableInt(TIMER0);
    ETIMER_DisableInt(TIMER1);
    sysDisableInterrupt(IRQ_TIMER0);
    sysDisableInterrupt(IRQ_TIMER1);

    return u8IntTestPass;
}

/*** (C) COPYRIGHT 2013 Nuvoton Technology Corp. ***/
